package com.imooc.netty.websocket;

import com.imooc.SpringUtil;
import com.imooc.enums.MsgActionEnum;
import com.imooc.pojo.ChatMsg;
import com.imooc.service.UserService;
import com.imooc.service.impl.UserServiceImpl;
import com.imooc.utils.JsonUtils;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.concurrent.GlobalEventExecutor;
import org.apache.commons.lang3.StringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

// 处理消息的handler
// 在netty 中，是用于专门为websocket处理文本的对象，frame 是消息的载体
public class ChatHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {


    // 用于记录和管理所有的channle
    public static ChannelGroup clients = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);


    // 当客户端连接服务端之后，获取客户端的channle，并且放到ChannelGroup 中进行管理
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        clients.add(ctx.channel());
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
       cause.printStackTrace();
       ctx.channel().close();
       clients.remove(ctx.channel());
    }

    //用户离开
    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        clients.remove(ctx.channel());
        System.out.println("客户端断开,channle对应的长id 为" + ctx.channel().id().asLongText());
        System.out.println("客户端断开,channle对应的短id 为" + ctx.channel().id().asShortText());
    }

    // 当前情况下，消息是群发的
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {

         // 获取客户端传送过来的消息
        String content =  msg.text();
        System.out.println("接收到的数据: "+content);

        Channel currentChannel = ctx.channel();

        // 对json 字符串进行解析成java 对象
        DataContent dataContent = JsonUtils.jsonToPojo(content,DataContent.class);

        Integer action = dataContent.getAction();

        // 连接状态
        if(action == MsgActionEnum.CONNECT.type){

          String senderId =  dataContent.getChatMsg().getSendUserId();

          UserChannelRel.put(senderId,currentChannel);


        }else if (action == MsgActionEnum.CHAT.type){
            // 客户端发送消息过来的状态

          ChatMsg chatMsg = dataContent.getChatMsg();

          String msgtext = chatMsg.getMsg();

          String receiverId = chatMsg.getAcceptUserId();

          String senderId = chatMsg.getSendUserId();

          // 把接收到的消息保存到数据库，并标记为未签收

          UserServiceImpl userService = (UserServiceImpl) SpringUtil.getBean("userServiceImpl");

           String msgid = userService.saveMsg(chatMsg);

           chatMsg.setMsgId(msgid);

           chatMsg.setId(msgid);

           dataContent.setChatMsg(chatMsg);

          Channel receiverChannel =  UserChannelRel.get(receiverId);

          if(receiverChannel == null){
              // 为空，代表用户离线，推送消息(Jpush,个推,小米推送)
          }else{
              // 当前用户在线
              Channel findChannel = clients.find(receiverChannel.id());

              if(findChannel != null){
                receiverChannel.writeAndFlush(new TextWebSocketFrame(JsonUtils.objectToJson(dataContent)));
              } else{
                  // 用户离线，推送
              }

          }

          // 离线，接收不到休息，在线，接收消息但是没打开，还是未读

        }else if (action == MsgActionEnum.SIGNED.type){
            // 客户端 接收了消息后发送过来的信息
        // 用户在线，且已经查看了消息，则客户端向服务端发送此消息，把消息的id,添加到extend 这个字段当中
         // 服务端取出这个字段的消息id，进行批量的接收处理，把flag置为1

         UserServiceImpl userService = (UserServiceImpl) SpringUtil.getBean("userServiceImpl");
         // 表示的是msg在数据库中的id ，根据这个 id 找到 对应的 msg ， 把它置成已读
         String msgIdsStr = dataContent.getExtend();
         String msgIds [] = msgIdsStr.split(",");

            List<String> msgIdList = new ArrayList<>();

            for(String mid : msgIds){

                if(StringUtils.isNotBlank(mid)){
                    msgIdList.add(mid);
                }

            }

            System.out.println(msgIdList.toString());

            if(msgIdList != null && !msgIdList.isEmpty() && msgIdList.size() > 0){
                // 批量签收
                userService.updateMsgSigned(msgIdList);
            }

        }else if(action == MsgActionEnum.KEEPALIVE.type){
            // 心跳
            System.out.println("收到来自channel 为 [" + currentChannel + "] 的 心跳包");
        }


    }
}
